package com.y.fund.web.com;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.y.fund.aacore.data.DataVo;
import com.y.fund.aacore.vo.PagingVo;
import com.y.fund.config.ResoConfig;
import com.y.fund.domain.com.CO02FileInfo;
import com.y.fund.handler.CurrLgnUserVo;
import com.y.fund.service.UploadService;
import com.y.fund.utils.FileUtil;
import com.y.fund.utils.IdGenerator;
import com.y.fund.utils.SQLUtil;
import com.y.fund.utils.StrUtil;
import com.y.fund.web.BaseController;
import com.y.fund.web.aavo.com.UploadVo;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@ApiSort(101)
@RestController
@Tag(name= "文件管理")
@RequestMapping(value = "api/com/file", produces = MediaType.APPLICATION_JSON_VALUE)
public class FileController extends BaseController{

	@Autowired
	private UploadService uploadService;

	@Autowired
	ResoConfig resoConfig;

    
    @GetMapping(value = "/list")
    @Operation(summary = "文件列表分页")
    @ApiOperationSupport(order = 1)
    public DataVo userList(CO02FileInfo fileInfo, PagingVo pvo) {
    	return DataVo.Success(commService.findPagingByExpLikeOrderCountById(fileInfo, pvo, SQLUtil.CreateTimeDescOrder));
    }
    
	/**
	 result：
	{
	    "code": 10000,
	    "err_msg": null,
	    "id": "20200825110932280711000448909884",
	    "path": "/2020/08/25/20200825110932280711000448909884.json",
	    "originalName": "AnnotationFlow_FFR_DEMO_v0.8_import.json"
	}
	 */
    @Operation(summary="文件上传存储")
	@PostMapping(value = "/upload")
	@ApiOperationSupport(order = 1)
	public DataVo singleFileUpload(HttpServletRequest req, HttpServletResponse res,
								   @RequestParam(name = "bizId", required = false) String bizId,
								   @RequestParam(name = "bizFlag", required = false) String bizFlag,
								   @RequestParam(name = "bizTag", required = false) String bizTag,
								   @RequestParam(name = "name", required = false) String name,
								   @RequestParam("file") MultipartFile file) throws Exception {

		if (null == file || StrUtil.isBlank(file.getOriginalFilename())) {
			return DataVo.Fail("请上传正确的文件");
		}

		final String relativeDir = FileUtil.NewRelativeDir();

		String uploaderId = req.getParameter("uploaderId");
		if(StrUtil.isBlankIncNullStr(uploaderId) && null != CurrLgnUserVo.Get()) {
			uploaderId = CurrLgnUserVo.Get().getUserId();
		}
		String uploaderName = req.getParameter("uploaderName");
		if(StrUtil.isBlankIncNullStr(uploaderName) && null != CurrLgnUserVo.Get()) {
        	 uploaderName = CurrLgnUserVo.Get().getUserName();
		}
		String originalName = file.getOriginalFilename();
		originalName = StrUtil.replaceAll(originalName, "\\", "/");
		if(originalName.indexOf("/")!=-1){
			originalName = originalName.substring(originalName.lastIndexOf("/"));
		}
		String ext = FileUtil.GetSuffix(originalName);
   		if(FileUtil.dangerSuffixs.contains(ext)){
			return DataVo.Fail("文件格式不正确");
		}
   		String writeFileName = IdGenerator.Id26WithoutYearMonthDay().concat(ext);

   		final String relPath = relativeDir.concat("/").concat(writeFileName);

   		final String fileId = IdGenerator.Id32();

   		DataVo upload = null;
		upload = uploadService.upload2Disk(file, bizFlag, relativeDir, writeFileName, true);

   		if(null==upload) {
			return DataVo.Fail("文件存储失败");
   		}else if(!DataVo.IsSuc(upload)) {
   			return upload;
   		}

		CO02FileInfo fi;


		String url = FileUtil.ConcatPath(resoConfig.getDiskDownloadUrl(), relPath);
		fi = new CO02FileInfo(bizId, bizFlag);
		fi.setId(fileId);
		fi.setRelPath(relPath);
		fi.setBizTag(bizTag);
		fi.setName(StrUtil.isBlankIncNullStr(name) ? originalName : name);
		fi.setUploaderId(uploaderId);
		fi.setUploaderName(uploaderName);
		fi.setSize(file.getSize());
		fi.setType(ext);
		fi.setUrl(url);
		commService.addObj(fi);
	
		UploadVo uv = new UploadVo(fi.getRelPath(), fi.getName(), fi.getUrl());
		uv.setBizId(bizId);
		uv.setBizFlag(bizFlag);
		uv.setFileId(fileId);
		uv.setSize(file.getSize());

		return DataVo.Success(uv);
	}

    @GetMapping(value="/urlbybiz")
	@Operation(summary="通过bizId和bizFlag获取文件下载url")
    @ApiOperationSupport(order = 3)
    public DataVo getUrlByBiz(HttpServletRequest req, @RequestParam(name="bizFlag") String bizFlag, @RequestParam(name="bizId") String bizId){
    	if(StrUtil.isBlankIncNullStr(bizFlag) || StrUtil.isBlankIncNullStr(bizId)) {
    		return DataVo.FailMustParam("bizFlag,bizId");
    	}
		String urls;
		try {
			CO02FileInfo info = new CO02FileInfo(bizId, bizFlag);
			List<CO02FileInfo> fileList = commService.findListByExample(info, null, SQLUtil.CreateTimeDescOrder);
			if (null==fileList || fileList.size()<1) {
				return DataVo.Fail("未查询到文件下载地址哦~");
			}

            urls = fileList.stream().map(file -> FileUtil.ConcatPath(resoConfig.getDiskDownloadUrl(), file.getRelPath()))
                    .collect(Collectors.joining());
		} catch (Exception e) {
			e.printStackTrace();
    		return DataVo.Fail("文件地址访问失败");
		}
		return DataVo.Success(urls);
	}


	@ResponseBody
	@GetMapping("download/{fpath}")
	@Operation(summary="根据文件相对路径下载文件")
	public void downloadByPath(HttpServletRequest req, HttpServletResponse res,
							   @PathVariable(name = "fpath") final String fpath,
							   @RequestParam(name = "bizFlag", required = false) String bizFlag,
							   @RequestParam(name = "fname", required = false) String fname) throws Exception {
		if (StrUtil.isBlankIncNullStr(fpath)) {
			return;
		}


		String path = FileUtil.ConcatPath(resoConfig.getDiskUpload(), fpath);
		File readFile = new File(path);

		res.setHeader("content-type", "application/octet-stream");
        res.setContentType("application/octet-stream");
        if(StrUtil.isBlankIncNullStr(fname)) {
        	String fp = StrUtil.replaceAll(fpath, "\\", "/");
        	if(fp.lastIndexOf("/") > 0) {
            	fname = fp.substring(fp.lastIndexOf("/") + 1);
        	}else {
        		fname = fpath;
        	}
        }
        res.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fname, "UTF-8"));

        ServletOutputStream outputStream = res.getOutputStream();

		byte[] bytes = new byte[1024*10];
        int read;
        try (FileInputStream fis = new FileInputStream(readFile)) {
        	do {
                read = fis.read(bytes);
                outputStream.write(bytes,0,read);
            }while (-1 != read);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }

	@ResponseBody
	@GetMapping("/downloadbyfid/{fileId}")
	@Operation(summary="根据文件ID下载文件 ")
	public void downloadByPath(HttpServletRequest req, HttpServletResponse res,
							   @PathVariable(name = "fileId") final String fileId,
							   @RequestParam(name = "fname", required = false) String fname) throws Exception{
		if(StrUtil.isBlankIncNullStr(fileId)) {
			return ;
		}

		CO02FileInfo fileInfo=commService.findObjById(CO02FileInfo.class,fileId);
		String relPath=fileInfo.getRelPath();
		String fileName=fileInfo.getName();
		if(StrUtil.NotBlankIgnoreNullStr(fname)) {
			fileName=fname;
		}


		String path = FileUtil.ConcatPath(resoConfig.getDiskUpload(), relPath);
		File readFile = new File(path);

		res.setHeader("content-type", "application/octet-stream");
		res.setContentType("application/octet-stream");
		if(StrUtil.isBlankIncNullStr(fileName)) {
			String fp = StrUtil.replaceAll(relPath, "\\", "/");
			if(fp.lastIndexOf("/") > 0) {
				fileName = fp.substring(fp.lastIndexOf("/") + 1);
			}else {
				fileName = relPath;
			}
		}
		res.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

		ServletOutputStream outputStream = res.getOutputStream();


		byte[] bytes = new byte[1024*10];
        int read;
        try (FileInputStream fis = new FileInputStream(readFile)) {
        	do {
                read = fis.read(bytes);
                outputStream.write(bytes,0,read);
            }while (-1 != read);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
	}

	@Operation(summary="文件删除")
	@DeleteMapping("/{fileId}")
	public DataVo delFile(@PathVariable(value = "fileId") String fileId) {
		return commService.delObjById(CO02FileInfo.class, fileId);
	}

	@Operation(summary="将文件从内网转为外网可访问")
	@DeleteMapping("innertopub")
	public DataVo innerToPubUrl(@PathVariable(value = "fileId") String fileId) {
		return commService.delObjById(CO02FileInfo.class, fileId);
	}
}
